//
// Copyright (c) 2009 All Right Reserved
//
// vl
//
// 2009-01-01
// Contains ...
using System;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Text;
using System.Xml.Serialization;
namespace LargoCommon.Music
{
/// Musical system.
/// System is prototype of so called formal GSystem. It is defined by
/// its order. System Contains a simple support for converting indexes into formal indexes.
/// It serves as a common superclass for harmonic and rhythmical GSystem.
/// Class helps to work with binary structures.
[Serializable]
[XmlRoot]
public class GeneralSystem {
/// Maximum (now supported) number of the system order.
public const byte MaxOrder = 24;
///
/// System degree.
///
private byte degree;
///
/// System order.
///
private byte order;
#region Constructors
/// Initializes a new instance of the GeneralSystem class. Serializable.
public GeneralSystem() {
}
/// Initializes a new instance of the GeneralSystem class.
/// Degree of system.
/// Order of system.
public GeneralSystem(byte degree, byte order) {
if (degree == 0) {
throw new ArgumentException("Degree of system must not be 0.");
}
if (order == 0) {
throw new ArgumentException("Order of system must not be 0.");
}
this.Degree = degree;
this.Order = order;
this.Median = (byte)(this.Order / 2);
}
#endregion
#region Properties
/// Gets or sets degree of the system.
/// Degree=2 for binary systems.
public byte Degree {
get {
Contract.Ensures(Contract.Result() > 0);
if (this.degree <= 0) {
throw new InvalidOperationException("Degree is not positive number.");
}
return this.degree;
}
set {
if (value <= 0) {
throw new ArgumentException("Degree must be positive number.", nameof(value));
}
this.degree = value;
}
}
/// Gets or sets order of the system, i.e. total number of bits).
/// Property description.
public byte Order {
get {
Contract.Ensures(Contract.Result() > 0);
if (this.order <= 0) {
throw new InvalidOperationException("Order is not positive number.");
}
return this.order;
}
set {
if (value <= 0) {
throw new ArgumentException("Order must be positive number.", nameof(value));
}
this.order = value;
}
}
/// Gets or sets median i.e. half order of the system.
/// Property description.
[XmlIgnore]
public byte Median { get; set; }
#endregion
#region Static methods
///
/// Convert Struct.
///
/// Structural number.
/// System Order From.
/// System Order To.
/// Returns value.
public static long ConvertStruct(long structNumber, byte sysOrderFrom, byte sysOrderTo) { //// byte sysDegree
if (sysOrderFrom == sysOrderTo) {
return structNumber;
}
var rstruct = 0L;
for (byte indexFrom = 0; indexFrom < sysOrderFrom; indexFrom++) {
if (!BinaryNumber.ElementIsOn(structNumber, indexFrom))
{
continue;
}
var ito = (byte)(int)Math.Round((double)indexFrom * sysOrderTo / sysOrderFrom);
rstruct = rstruct | BinaryNumber.BitAt(ito);
}
//// long rstruct = (long)struct * (long)((Math.Pow(sysDegree, sysOrderTo) - 1) / (Math.Pow(sysDegree, sysOrderFrom) - 1));
return rstruct;
}
/// Converts the integer index to its formal system representative element.
/// Order of the system.
/// Real system length.
/// Returns value.
[JetBrains.Annotations.PureAttribute]
public static byte FormalLength(byte order, int sysLength) {
if (order == 0) {
return 0;
}
//// Time optimization
if (sysLength < 0) {
//// if (sysLength < -order) { sysLength += order + order; }
while (sysLength < 0) {
sysLength += order;
}
}
else {
if (sysLength < order) {
return (byte)sysLength;
}
while (sysLength >= order) {
sysLength -= order;
}
}
//// int frmLength = sysLength % order;
//// return (byte)((frmLength < 0) ? (frmLength + order) : frmLength);
return (byte)sysLength;
}
#endregion
/// Returns symbols for given element.
/// Returns value.
[JetBrains.Annotations.PureAttribute]
public long LongSize() {
return (long)Math.Pow(this.Degree, this.Order);
}
/// Returns symbols for given element.
/// Returns value.
[JetBrains.Annotations.PureAttribute]
public decimal DecimalSize() {
return (decimal)Math.Pow(this.Degree, this.Order);
}
/// Converts the integer index to its formal system representative element.
/// Real system length.
/// Returns value.
[JetBrains.Annotations.PureAttribute]
public byte FormalLength(int sysLength) {
return FormalLength(this.Order, sysLength);
}
/// Converts the integer index to its formal system representative number.
/// Real system length.
/// Returns value.
[JetBrains.Annotations.PureAttribute]
public int FormalMedianLength(int sysLength) {
int frmLength = this.FormalLength(sysLength);
return frmLength <= this.Median ? frmLength : (frmLength - this.Order);
}
#region String representation
/// String representation of the object.
/// Returns value.
[JetBrains.Annotations.PureAttribute]
public override string ToString() {
var s = new StringBuilder();
s.AppendFormat(CultureInfo.CurrentCulture, "${0,2}", this.Order.ToString("D", CultureInfo.CurrentCulture.NumberFormat));
return s.ToString();
}
#endregion
}
}